#ifndef DATACENTER_H
#define DATACENTER_H

#include <QObject>
#include <QList>
#include <QFile>
#include <QDir>
#include <QStandardPaths>
#include <QJsonObject>
#include <QJsonDocument>

#include "data.h"
#include "../network/netclient.h"

#include "gateway.qpb.h"
#include "user.qpb.h"
#include "friend.qpb.h"
#include "message_storage.qpb.h"
#include "message_transmit.qpb.h"

namespace model {

class DataCenter : public QObject
{
    Q_OBJECT
public:
    static DataCenter* getInstance();
    ~DataCenter();

    void initWebsocket();
    void sendAuthentication();  // 身份验证

    // 数据持久化三步曲
    void initDataFile();
    void saveDataFile();
    void loadDataFile();

    void addUnreadMsg(const QString& chatSessionId);
    void clearUnreadMsg(const QString& chatSessionId);

    void ping() { m_netClient.ping(); }

    void getMyselfAsync();
    void resetMyself(const im::GetUserInfoRsp& resp);  // 重设个人信息

    void getFriendListAsync();
    void resetFriendList(const im::GetFriendListRsp& resp);  // 重设好友列表信息

    void getChatSessionListAsync();
    void resetChatSessionList(const im::GetChatSessionListRsp& resp);   // 重设会话列表信息

    void getApplyListAsync();
    void resetApplyList(const im::GetPendingFriendEventListRsp& resp);  // 重设好友申请信息

    void getRecentMsgListAsync(const QString& chatSessionId, bool isUI);    // 缓存服务器上的聊天内容，isUI表示是否在界面上呈现出来
    void resetRecentMsgList(const QString& chatSessionId, const im::GetRecentMsgRsp& resp);  // 重设缓存服务器上的聊天内容
    chatSessionInfo* findChatSessionBySessionId(const QString& chatSessionId);  // 根据会话id 搜索 会话信息

    chatSessionInfo* findChatSessionByUserId(const QString& userId);  // 根据用户id 搜索 会话信息
    void topChatSessionInfo(const chatSessionInfo& chat);       // 把会话置顶

    void sendMessageAsync(const QString& id, const QString& content);  // 让网络中心处理发送 发送文字消息的网络请求
    void sendImageMessageAsync(const QString& id, const QByteArray& content);   // 让网络中心处理发送 发送图片消息的网络请求
    void sendFileMessageAsync(const QString& id, const QString& fileName, const QByteArray& content);   // 让网络中心处理发送 发送文件消息的网络请求
    void sendSpeechMessageAsync(const QString &chatSessionId, const QByteArray &content);   // 让网络中心处理发送 发送语音的网络请求
    void addMessage(const Message& msg);  // 在会话列表缓存里添加信息

    void receiveMessage(const QString& chatSessionId);  //  处理接收到的聊天信息内容

    void changeNickNameAsync(const QString& newNick);   // 让网络中心处理发送 修改昵称的网络请求
    void resetNickName(const QString& newNick);     // 修改呢称缓存

    void changeDescriptionAsync(const QString& description); // 让网络中心处理发送 修改签名的网络请求
    void resetDescption(const QString& description);  // 修改签名缓存

    void changeAvatarAsync(const QByteArray& imageByte);    // 让网络中心处理发送 修改头像的网络请求
    void resetAvatar(const QByteArray& avatar);     // 修改头像缓存

    void getVerifyCodeAsync(const QString& phone);  // 让网络中心处理发送 获取验证码的网络请求
    void resetVerifyCode(const QString& verifyCode);// 修改验证码缓存

    void changePhoneAsync(const QString& phoneTochange, const QString& codeID, const QString& code);    // 让网络中心处理发送 修改手机号的网络请求
    void resetPhone(const QString& phone);// 修改手机号缓存

    void deleteFriendAsync(const QString& userId);  // 让网络中心处理发送 删除好友的请求
    void removeFriend(const QString& userId);   // 删除好友以及相应的会话列表

    void addFriendApplyAsync(const QString& userId);    // 让网络中心处理发送 添加好友的请求

    void acceptFriendApplyAsync(const QString& userId); // 让网络中心处理发送 同意好友的请求
    UserInfo removeFromApplyList(const QString& userId); // 移除好友申请以及相应的会话列表

    void createGroupChatSessionAsync(const QList<QString>& member);  // 让网络中心处理发送 创建群信息

    void getMemberListAsync(const QString& chatSessionId); // 让网络中心处理发送 加载群成员的请求
    void resetMemberList(const QString& chatSessionId, const QList<im::UserInfo>& memberList);  // 修改群成员列表缓存

    void searchUserAsync(const QString& searchKey);     // 让网络中心处理发送 搜索用户的请求
    void resetSearchUserResult(const QList<im::UserInfo>& userList);    // 修改搜索列表缓存

    void searchMessageAsync(const QString& searchKey);  // 让网络中心处理发送 按关键字搜索历史消息的请求
    void searchMessageByTimeAsync(const QDateTime &begTime, const QDateTime &endTime);  // 让网络中心处理发送 按日期搜索历史消息的请求
    void resetSearchMessageResult(const QList<im::MessageInfo>& messageResult);

    void userLoginAsync(const QString& user, const QString& password);  // 让网络中心处理发送 用户账号登入的请求
    void resetLoginSessionId(const QString& loginSessionID);
    void userRegisterAsync(const QString& user, const QString& password);// 让网络中心处理发送 用户账号注册的请求

    void phoneLoginAsync(const QString& phone, const QString& verifyCodeId, const QString& verifyCode); // 让网络中心处理发送 手机号登入的请求
    void phoneRegisterAsync(const QString& phone, const QString& verifyCode); // 让网络中心处理发送 手机号注册的请求

    void getSingleFileAsync(const QString& fileId); // 让网络中心处理发送 获取单个文件的请求
    void speechConvertTextAsync(const QString& fileId, const QByteArray& content); // 让网络中心处理发送 语音转文字的请求

public:
    const QString getLoginSessionId() { return m_loginSessionId; }
    const UserInfo* getMyself() { return m_myself; }
    QList<UserInfo>* const getFriendList() { return m_friendList; }
    QList<chatSessionInfo>* const getChatSessionList() { return m_chatSessionList; }
    QList<UserInfo>* const getApplyList() { return m_applyList; }
    QList<UserInfo>* getMemberList(const QString& chatSessionId);
    const QList<Message>* getRecentMsgList(const QString& chatSessionId);
    const QString& getCurrentChatSessionId() { return m_currentChaSessionId; }
    int getUnreadMsg(const QString& chatSessionId) { return (*m_unreadMessageCount)[chatSessionId]; }
    const QList<UserInfo>* getSearchUserResult() { return m_searchUserResult; }
    const QList<Message>* getSearchMessageResult() { return m_searchMessageResult; }
    const QString& getVerifyCodeId() { return m_currentVerifyCodeId; }
    UserInfo* getFriendById(const QString& userID);

    void setCurrentChatSessionId(const QString& chatSessionId);

private:
    // 登入会话，成功登入后，
    // 服务器返回，然后持久化保存，
    // 用户显示点击“退出登录”，则删除这个信息
    QString m_loginSessionId = "";
    UserInfo* m_myself = nullptr;		// 当前用户信息
    QList<UserInfo>* m_friendList = nullptr;		// 当前用户好友列表
    QList<chatSessionInfo>* m_chatSessionList = nullptr;    // 当前用户的会话列表
    QString m_currentChaSessionId;      // 当前用户选择的消息会话 id
    QList<UserInfo>* m_applyList = nullptr;       // 待处理的好友申请列表
    QHash<QString, QList<UserInfo>>* m_memberList = nullptr;		// 每个会话中的用户列表
    QHash<QString, QList<Message>>* m_recentMessages = nullptr;     // 当前用户等等消息内容，key 为 ChatSessionInfo 的 chatSessionId
    QHash<QString, int>* m_unreadMessageCount = nullptr;            // 未读消息数目的统计，key 为 chatSessionInfo，chatSessionId，value 为未读消息个数
    QList<UserInfo>* m_searchUserResult = nullptr;                // 用户搜索结果
    QList<Message>* m_searchMessageResult = nullptr;              // 当前历史消息搜索结果
    QString m_currentVerifyCodeId;              // 当前短信验证码的验证 id
    network::NetClient m_netClient;

    explicit DataCenter(QObject *parent = nullptr);

signals:
    void getMyselfDone();
    void getFriendListDone();
    void getChatSessionListDone();
    void getApplyListDone();
    void getRecentMsgListDone(const QString& chatSessionId);    // 获取聊天内容并呈现出来
    void getRecentMsgListDoneNoUI(const QString& chatSessionId);// 获取聊天内容不呈现出来
    void sendMessageDone(MessageType messageType, const QByteArray &content, const QString &extraInfo);
    void updateLastMessage(const QString& chatSessionId);   // 更新最新一条消息
    void receiveMessageDone(const Message& msg);        // 发送信号让界面更新其他人发来的聊天信息
    void changeNickNameDone();          // 发送信号让界面更新 昵称
    void changeDescriptionDone();       // 发送信号让界面更新 签名
    void changeAvatarDone();            // 发送信号让界面更新 头像
    void changePhoneDone();             // 发送信号让界面更新 手机号的相关按钮
    void getVerifyCodeDone();           // 发送信号让界面更新 验证码按钮
    void deleteFriendDone();            // 发送信号让界面更新 删除好友之后的相关界面
    void addFriendApplyDone();          // 发送信号 提示已经发送了好友申请
    void receiveFriendApplyDone();      // 发送信号让界面更新 发送添加好友申请之后的相关界面
    void clearCurrentSession();         // 发送信号让界面 清空聊天窗口界面
    void acceptFriendApplyDone();       // 发送信号让界面 更新好友申请，好友界面
    void receiveFriendProcessAccept();  // 发送信号让界面 更新好友列表界面
    void createGroupChatSessionDone();  // 发送信号给服务器 创建群信息
    void receiveSessionCreateDone();    // 发送信号给界面 更新会话窗口
    void getMemberListDone(const QString& chatSessionId);           // 发送信号给界面 更新群成员窗口
    void searchUserDone();              // 发送信号给界面 更新用户搜索框内容
    void searchMessageDone();           // 发送信号给界面 更新历史消息搜索框内容
    void userLoginDone(bool success, const QString& err);   // 发送信号给界面 提示账号登入是否有误
    void userRegisterDone(bool success, const QString& err);// 发送信号给界面 更新账号注册情况
    void phoneLoginDone(bool success, const QString& err);   // 发送信号给界面 提示手机号登入是否有误
    void phoneRegisterDone(bool success, const QString& err);// 发送信号给界面 更新手机号注册情况
    void getSingleFileDone(const QString& fileID, const QByteArray &content); // 发送信号并携带数据给界面 更新界面数据内容
    void speechConvertTextDone(const QString& fileID, const QString &text); // 发送信号并携带数据给界面 更新界面语音转文字
};
} // end namespace

#endif // DATACENTER_H
